package model

import (
	"OJCenter/global"
	"OJCenter/tool"
	"bytes"
	"fmt"
	"net/smtp"
	"strings"
	"time"
)

func (m *Model) SendMail(toAddr string, verificationCode int) error {
	sender := global.Conf.MailConf.Sender
	host := global.Conf.MailConf.Host
	password := global.Conf.MailConf.Pwd
	mailtype := "html"
	subject := global.Conf.MailConf.Subject
	_body := fmt.Sprintf("<html><body><h3>尊敬的用户：<br><br> 您的验证码为：%d，该验证码在 5分钟内有效</h3></body></html>", verificationCode)
	body := tool.Base64Encode([]byte(_body))
	sendInfo := fmt.Sprintf(" sender:%v, to:%v, host:%v, subject:%v,  mailType:%v", sender, toAddr, host, subject, mailtype)
	global.Logger.Info(sendInfo)
	var user string
	user = sender
	if strings.Contains(sender, ";") {
		strs := strings.Split(sender, ";")
		user = strs[1]
		sender = strs[0]
	}
	hp := strings.Split(host, ":")
	// auth := smtp.PlainAuth("", user, password, hp[0])
	auth := PlainAuthOverTLSConn(user, password, hp[0])
	contentType := "Content-Type: text/" + mailtype + "; charset=UTF-8" + "\r\n"

	subject = fmt.Sprintf("=?UTF-8?B?%s?=", tool.Base64Encode([]byte(subject)))
	sendTo := strings.Split(toAddr, ";")
	// msg := []byte("To: " + to + "\r\nFrom: " + sender + "<" + sender + ">\r\nSubject: " + subject + "\r\n" + content_type + "\r\n\r\n" + body)
	buffer := bytes.NewBuffer(nil)
	Header := make(map[string]string)
	Header["From"] = sender
	Header["To"] = toAddr
	// 使用时间戳-发件人作Message-Id，符合RFC 2822标准
	id := time.Now().UnixNano()
	Header["Message-Id"] = fmt.Sprintf("<%v-%v>", id, sender)
	// 符合RFC 2822标准的时间格式
	Header["Date"] = time.Now().Format("Mon, 02 Jan 2006 15:04:05 -0700")
	Header["Mime-Version"] = "1.0"
	boundary := "MyBoundary"
	// 定义消息体为multipart/mixed(支持邮件内容为纯文本、超文本、内嵌资源和附件)，并指定boundary参数的字符串
	Header["Content-Type"] = "multipart/mixed;boundary=" + boundary
	Header["Subject"] = subject
	writeHeader(buffer, Header)

	// 邮件体中可以包含多个段，所有的子段都以“--”+boundary行开始，父段以“--”+boundary+“--”行结束。
	// 段开始
	mailBody := "\r\n--" + boundary + "\r\n"
	mailBody += contentType
	// 邮件正文的编码方式为base64
	mailBody += "Content-Transfer-Encoding:" + "base64" + "\r\n"
	buffer.WriteString(mailBody + "\r\n")

	// 根据RFC822规定，BASE64编码每行不超过76个字符
	for i, l := 0, len(body); i < l; i++ {
		buffer.WriteByte(body[i])
		if (i+1)%76 == 0 {
			buffer.WriteString("\r\n")
		}
	}
	buffer.WriteString("\r\n")
	// 段结束
	buffer.WriteString("\r\n--" + boundary + "--")
	err := smtp.SendMail(host, auth, sender, sendTo, buffer.Bytes())
	if err != nil {
		global.Logger.Errorf("BaseInfo:%v, Send Mail fail err: %v", sendInfo, err)
	}
	return err
}

func PlainAuthOverTLSConn(username, password, host string) smtp.Auth {
	return smtp.PlainAuth("", username, password, host)
}

func writeHeader(buffer *bytes.Buffer, Header map[string]string) string {
	header := ""
	for key, value := range Header {
		header += key + ":" + value + "\r\n"
	}
	header += "\r\n"
	buffer.WriteString(header)
	return header
}

func (m *Model) SetVerifyCode(uid int64, code uint32) error {
	return m.U.InsertMailCodeInfo(uid, code)
}

func (m *Model) GetVerifyCode(uid int64) (uint32, error) {
	return m.U.GetMailInfo(uid)
}
